// SPDX-License-Identifier: GPL-2.0 or GPL-3.0
// Copyright © 2019 Ariadne Devos

#ifndef _sHT_LEX_IPv4_ADDR
#define _sHT_LEX_IPv4_ADDR

#include <sHT/logic/failbit.h>

/** *Perhaps* a numeric IP address parsed from a string */
struct s2_ipv4_maybe
{
	/** The IP address' numeric value

	  Byte order: "127.0.0.1" -> 0x7f000001.
	  The byte order of 0x7f000001 depends
	  on the implementation of C (ABI, CPU). */
	uint32_t ip;
	/* one-past-end last last correct byte,
	  -- if not fully parsed, the failbit is set. */
	sHT_with_failbit
	size_t end;
};

/** Parse a IPv4 address from an ASCII string into a number.

  The match is made as long as possible!

  If there is not match, `ret.end` is set to the first incorrect
  byte -- non-speculatively, all before were [0-9.] (may be useful
  to reduce backtracking).

  Requires:
  (a): 0 < length < failbit_limit(size_t)
    (* the string, not the buffer, begins at 1 *)
  (b): SliceCap(read ^ set, length, from)

  Definition:
  (RFC 3986, URI: Generic Syntax, 3.2.2 Host, p. 20)

  (* ABNF + regex-capture *)
  IPv4address := (dec-octet) "." (dec-octet) "." (dec-octet) "." (dec-octet)
  (abbreviated) IPv4address = dec-octet ("." dec-octet){3}
  dec-octet := [0-9] / [1-9] [0-9] / "1" [0-9]{2} / "2" [0-4][0-9] / "25" [0-5]

  (* dec-octet is interpreted as a natural < 256 (see <sHT/lex/nat.h>),
    IPv4address is formed by concatenating the `dec-octet`s into a uint32_t.
    *)
  end := maximalise (noexist → 0) {k | 1 ≤ k ≤ length }
    [\0, \1, \2, \3] <- do match IPv4address from 1 length
  value := (mappend . (map (->octet . ->nat)) [\0 .. \3]

  Ensures:
  (v): 0 ≤ fail_value(size_t, ret.end) ≤ length
  (w): nonspec: end ≠ 0 ↔ good(size_t, ret.end)
  (x): nonspec: good(size_t, ret.end) → fail_value(size_t, ret.end) = end
  (y): nonspec: good(size_t, ret.end) → ret.ip = value
  (z): nonspec: ¬good(size_t, ret.end)
    → match [0-9.]* from 1 fail_value(size_t, ret.end) */
__attribute__((pure))
struct s2_ipv4_maybe
s2_parse_ipv4(size_t length, const uint8_t from[length]);

#endif
